package com.lottery.htbc.thread;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lottery.htbc.dto.UserBetConfigDto;
import com.lottery.htbc.service.LuckDrawServiceImpl;
import com.lottery.htbc.utils.DateUtils;
import com.lottery.htbc.utils.FastJsonUtils;
import com.lottery.htbc.utils.SSLHttpClientUtil;
import com.lottery.htbc.utils.StringUtils;
import com.lottery.htbc.utils.service.redis.RedisService;


@SuppressWarnings("rawtypes")
public class LuckDrawBase {


	private final static Logger LOGGER = LoggerFactory.getLogger(LuckDrawBase.class);

	/**
	 * 一分钟对应的秒
	 */
	protected  static  final  int  MINUTE=60;
	/**
	 * 防止重复投的  round_id的过期时间
	 * 分钟
	 */
	protected  static  final  int  REPEAT_TIME=10;

	/**
	 * redis 操作对象
	 * 
	 */
	protected RedisService redisService;

	protected UserBetConfigDto betConfig;

	private LuckDrawServiceImpl luckDrawService;

	public LuckDrawBase(RedisService redisService, UserBetConfigDto betConfig,LuckDrawServiceImpl luckDrawService) {
		super();
		this.redisService = redisService;
		this.betConfig = betConfig;
		this.luckDrawService = luckDrawService;
	}
	public LuckDrawBase(Integer  roomId){
		this.roomId=roomId;
	}
	public LuckDrawBase(){

	}

	public void setRedisService(RedisService redisService) {
		this.redisService = redisService;
	}
	/**
	 * 判断账户是否能投注
	 * @return
	 */
	protected Boolean accountAhead(){
		String authStatus=redisService.get(betConfig.getAccount()+"_NO_AUTH");
		//是否登录超时(还地方登录)
		if(authStatus!=null){
			LOGGER.info("账户:{}不进行投注,原因是:{} ",betConfig.getAccount(),authStatus);
			LOGGER.info("\n");
			return false;
		}
		String invalidStatus=redisService.get(betConfig.getAccount()+"_INVALID_PARAMS");
		//是否登录超时(还地方登录)余额不足
		if(invalidStatus!=null){
			LOGGER.info("账户:{}不进行投注,原因是:{} ",betConfig.getAccount(),invalidStatus);
			LOGGER.info("\n");
			return false;
		}
		return true;
	}

	/**
	 * 初始化游戏环境
	 * @return
	 * @throws Exception
	 */
	public Map initGame() throws Exception{
		//初始化游戏环境
		String initGameUrl="https://keno.t66h99.com/api/api/v2/initGame?code=jspk10&token="+betConfig.getToken()+"&m=1";
		String initGameData= SSLHttpClientUtil.get(initGameUrl);
		//{"status":"NO_AUTH","content":{"summury":"您未游戏在页面停留时间过长，请重新登录"}}
		if(initGameData.indexOf("NO_AUTH")>-1){
			LOGGER.info("账户:{},初始化异常,异常信息为:{}",StringUtils.decode(initGameData));
			redisService.set(betConfig.getAccount()+"_NO_AUTH",StringUtils.decode(initGameData));
			LOGGER.info("\n");
			return null;
		}
		Map initMap= FastJsonUtils.stringToMap(initGameData);
		List<Map> roundMap= FastJsonUtils.toList(initMap.get("rounds").toString(),Map.class);
		if(roundMap!=null&&roundMap.size()>0){
			return roundMap.get(0);
		}
		else {
			return null;
		}
	}

	/**
	 * 投注
	 * @param prarm
	 */
	public void betting(Map prarm){
		LOGGER.info("账户:{},投注请求参数是:{}",betConfig.getAccount(),FastJsonUtils.mapToJSONString(prarm));
		String epoch=System.currentTimeMillis()+"";
		String cur= epoch.substring(0,10);
		String betUrl="https://keno.t66h99.com/api/api/offc/bets?token="+betConfig.getToken()+"&d="+cur;
		String betRs=  SSLHttpClientUtil.doPostJson(betUrl,FastJsonUtils.mapToJSONString(prarm));
		LOGGER.info("账户:{},投注请求返回的结果是:{}",betConfig.getAccount(),betRs);
		// 余额不足  {"status":"INVALID_PARAMS","content":{"summury":"余额不足"},"sys_time":1560642432}
		if(betRs.indexOf("INVALID_PARAMS")>-1){
			LOGGER.info("异常结果:"+StringUtils.decode(betRs));
			redisService.set(betConfig.getAccount()+"_INVALID_PARAMS",StringUtils.decode(betRs));
		}
		else{
			Map<String, Object> synMap=new HashMap<String, Object>();
			synMap.put("synToken", betConfig.getToken());
			synMap.put("account", betConfig.getAccount());
			synMap.put("userId", betConfig.getUserId());
			synMap.put("taskId", betConfig.getTaskId());
			synMap.put("roundId", prarm.get("round_id"));
			synMap.put("betValue", prarm.get("bet_value"));
			Map betMap=gainBetRs(betRs);
			if(betMap!=null&&betMap.get("round_no")!=null){
				synMap.put("roundNo", betMap.get("round_no"));
				synMap.put("betType", betMap.get("bet_type"));
				synMap.put("throwAmount", betMap.get("amount"));
			}
			String redisBsKey="HTBC_BS_INDEX_CURRENT_"+betConfig.getAccount();
			String bsIndex=redisService.get(redisBsKey);
			synMap.put("bsIndex", bsIndex);
			luckDrawService.saveWaitSynRecord(synMap);
			LOGGER.info("账户:{} 投注标识{} 返回单号{},成功加入等待同步:",betConfig.getAccount(),synMap.get("roundId"),synMap.get("roundNo"));
		}
	}

	/**
	 * 获取投将结果
	 * @param betRs
	 * @return
	 */
	private Map gainBetRs(String betRs){
		Map betMap=	FastJsonUtils.stringToMap(betRs);
		if(betMap!=null){
			String orders=	betMap.get("orders").toString();
			List<Map> orderList=FastJsonUtils.toList(orders, Map.class);
			if(orderList!=null&&orderList.size()>0){
				return orderList.get(0);

			}
		}
		return null;

	}

	/**
	 * 构造随机数 <br/>  根据betConfig 的zhu的数量决定随机数的个数
	 * @return
	 */
	protected  String constructionRd(){
		String rdStr="";
		Random rd=new Random();
		Set<Integer> setList=new HashSet<>();
		do {
			setList.add(rd.nextInt(9)+1) ;
		}while (setList.size()<betConfig.getZhu());
		boolean isFirst=true;
		for(Integer num:setList){
			String numStr="";
			if(num<10){
				numStr="0"+num;
			}
			else {
				numStr=""+num;
			}
			if(isFirst){
				rdStr+=numStr;
				isFirst=false;
			}
			else {
				rdStr+=" "+numStr;
			}
		}
		return  rdStr+",,,,,,,,,";
	}
	/**
	 * 构造大小或者单双
	 * @param atom 原子数字
	 * @param type 1:单双,2:大小
	 * @return
	 */
	protected  String constructionValue(int atom,int type){
		//大:56789,,,, 小:01234,,,,
		//单:13579,,,, 双:02468,,,,
		if(type==1){
			if(atom%2==0){
				return "02468,,,,";
			}
			else{
				return "13579,,,,";
			}
		}
		else{
			if(atom<5){
				return "01234,,,,";
			}
			else{
				return "56789,,,,";
			}
		}
	}

	public void winnerAnalysis(Boolean winFlag){
		winnerAnalysis( winFlag,this.betConfig.getAccount());
	}

	/**
	 * 中奖分析
	 * @param winFlag 是否中奖
	 */
	public void winnerAnalysis(Boolean winFlag,String account){
		String rediey="HTBC_"+DateUtils.getDays()+"_"+account;
		String hiTotalKey=rediey+"_hit_total";
		String hitContinueKey=rediey+"_hit_continue";
		String hitMaxKey=rediey+"_hit_max";
		String hitGradeKey=rediey+"_hit_grade_";
		String missTotalKey=rediey+"_miss_total";
		String missContinueKey=rediey+"_miss_continue";
		String missMaxKey=rediey+"_miss_max";
		String missGradeKey=rediey+"_miss_grade_";
		//24个小时
		int  milliseconds=MINUTE*60*24;
		try {
			if (winFlag) {
				//总中奖次数
				Object hitTotalObj = redisService.get(hiTotalKey);
				int hitTotal = 1;
				if (hitTotalObj != null) {
					hitTotal = Integer.valueOf(hitTotalObj.toString());
					hitTotal++;
				}
				redisService.set(hiTotalKey, hitTotal + "", milliseconds);
				//连续中奖次数
				Object hitContinueObj = redisService.get(hitContinueKey);
				int hitContinue = 1;
				if (hitContinueObj != null) {
					hitContinue = Integer.valueOf(hitContinueObj.toString());
					hitContinue++;
				}
				redisService.set(hitContinueKey, hitContinue + "", milliseconds);
				//统计和记录连续中奖次数
				if (hitContinue > 1) {
					hitGradeKey = hitGradeKey + "" + hitContinue;
					redisService.incr(hitGradeKey);
				}
				//最高连续中奖次数
				int hitMax = 1;
				Object hitMaxObj = redisService.get(hitMaxKey);
				if (hitMaxObj != null) {
					hitMax = Integer.valueOf(hitMaxObj.toString());
					if (hitContinue > hitMax) {
						hitMax = hitContinue;
						redisService.set(hitMaxKey, hitMax + "", milliseconds);
						LOGGER.info("账户{},连续[ 中奖 ]次数破新高,次数为:{}",account, hitMax);
					}
				} else {
					redisService.set(hitMaxKey, hitMax + "", milliseconds);
				}
				redisService.del(missContinueKey);
				LOGGER.info( "账户{},总[ 中奖 ]次数为:{},连续[ 中奖 ]次数为:{},目前最高连续[ 中奖 ]次数为:{},重置连续不中奖次数",account, hitTotal, hitContinue, hitMax);
			} else {
				Object missContinueObj = redisService.get(missContinueKey);
				int missContinue = 1;
				if (missContinueObj != null) {
					missContinue = Integer.valueOf(missContinueObj.toString());
					missContinue++;
				}
				redisService.set(missContinueKey, missContinue + "",
						milliseconds);
				Object misstotalObj = redisService.get(missTotalKey);
				int missTotal = 1;
				if (misstotalObj != null) {
					missTotal = Integer.valueOf(misstotalObj.toString());
					missTotal++;
				}
				redisService.set(missTotalKey, missTotal + "", milliseconds);
				//统计和记录连续不中奖次数
				if (missContinue > 1) {
					missGradeKey = missGradeKey + "" + missContinue;
					redisService.incr(missGradeKey);
				}
				//最高连续不中奖次数
				int missMax = 1;
				Object missMaxObj = redisService.get(missMaxKey);
				if (missMaxObj != null) {
					missMax = Integer.valueOf(missMaxObj.toString());
					if (missContinue > missMax) {
						missMax = missContinue;
						redisService
						.set(missMaxKey, missMax + "", milliseconds);
						LOGGER.info("账户{},连续[ 不中奖 ]次数破新高,次数为:{}",account, missMax);
					}
				} else {
					redisService.set(missMaxKey, missMax + "", milliseconds);
				}
				redisService.del(hitContinueKey);
				LOGGER.info( "账户{},总[ 不中奖 ]次数为:{},连续[ 不中奖 ]次数为:{},目前最高连续[ 不中奖 ]次数为:{},重置连续中奖次数",account, missTotal, missContinue, missMax);
			}
		} catch (Exception e) {
			LOGGER.error("账户:{},记录redis统计失败=======异常原因:{}",account,e.getMessage());
		}
	}

	/**
	 * 上一次是否中奖
	 * @return
	 * @throws Exception 
	 */
	public Boolean isWinning() throws Exception{
		gainBeforeRecord();
		return isWinning(this.beforeRecord);
	}
	/**
	 * 指定记录是否中奖
	 * @param beforeRecord
	 * @return
	 */
	public Boolean isWinning(Map beforeRecord){
		if(beforeRecord!=null&&beforeRecord.get("win_amount")!=null){
			Float winAmount= Float.valueOf(beforeRecord.get("win_amount").toString());
			if(winAmount>0){
				//winnerAnalysis(true);
				return true;
			}
			else{
				//winnerAnalysis(false);
				return false;
			}
		}
		return true;
	}

	/**
	 * 最后第一次投注记录
	 */
	protected Map beforeRecord;
	/**
	 * 最后第二次投注记录
	 */
	protected Map beforeRecord2;
	/**
	 * 最后第三次投注记录
	 */
	protected Map beforeRecord3;


	/**
	 * 获取最近三次次的投注纪录
	 * @return
	 * @throws Exception
	 */
	private  void  gainBeforeRecord()throws Exception{
		Map recordMap=queryRecord();
		List<Map> itemMap= FastJsonUtils.toList(recordMap.get("items").toString(),Map.class);
		if(itemMap!=null&&itemMap.size()>0){
			Map map=  itemMap.get(0);
			LOGGER.info("账户:{},上次投注信息:第[{}]期数, 具体信息:{}",betConfig.getAccount(),map.get("round_no"),map);
			beforeRecord=map;
			if(itemMap.size()>2){
				beforeRecord2=itemMap.get(1);
			}
			if(itemMap.size()>3){
				beforeRecord3=itemMap.get(2);
			}
		}
	}

	/**
	 * 房间id
	 */
	private Integer  roomId;
	public void setRoomId(Integer roomId) {
		this.roomId = roomId;
	}
	/**
	 * 获取当前用户的投将记录
	 * @return
	 * @throws Exception
	 */
	public Map queryRecord()throws Exception{
		return queryRecord(betConfig.getToken());
	}
	/**
	 * 获取指定token 的投将记录
	 * @param token
	 * @return
	 * @throws Exception
	 */
	public Map queryRecord(String token)throws Exception{
		String betUrl="https://keno.t66h99.com/api/api/offc/orders";
		Map<String ,Object> prarm=new HashMap<>();
		prarm.put("token",token);
		prarm.put("perpage",25);
		prarm.put("room_id",roomId);
		prarm.put("page",1);
		prarm.put("sort","{\"id\":\"DESC\"}");
		//LOGGER.info("请求参数为:{}",FastJsonUtils.toJSONString(prarm));
		String recordRs=   SSLHttpClientUtil.get(betUrl,prarm);
		Map recordMap= FastJsonUtils.stringToMap(recordRs);
		//LOGGER.info("请求返回的结果是:{}",recordRs);
		return recordMap;
	}

	/**
	 * 感应token 为了不让token失效
	 * @param token
	 * @throws Exception
	 */
	public void heartbeatByToken(String token)throws Exception{
		String initGameUrl="https://keno.t66h99.com/api/api/v2/initGame?code=jspk10&token="+token+"&m=1";
		String initGameData= SSLHttpClientUtil.get(initGameUrl);
		Map initMap= FastJsonUtils.stringToMap(initGameData);
		if(initMap!=null&&initMap.get("room")!=null){
			LOGGER.info("心跳感应>保持[token={}]有效 感应返回数据为:{}",token,initMap.get("room"));
		}
		else{
			LOGGER.info("心跳感应>保持[token={}]有效 感应返回数据为:{}",token,initGameData);
		}
	}

	public Map synBalance()throws Exception{
		return synBalance(betConfig.getToken());
	}
	/**
	 * 同步用户余额
	 * @param token 用户token
	 * @throws Exception
	 */
	public Map synBalance(String token)throws Exception{
		String synUrl="https://keno.t66h99.com/api/api/cqssc/login?token="+token+"&token="+token+"&d=1563247769";
		String synData= SSLHttpClientUtil.get(synUrl);
		LOGGER.info("[token={}]同步余额成功;返回数据为:{}",token,synData);
		Map synMap= FastJsonUtils.stringToMap(synData);
		return synMap;
	}

}
